package com.shuimin.group;

import com.shuimin.group.constant.Config;
import com.shuimin.group.constant.GroupStatus;
import com.shuimin.group.constant.UserRight;
import com.shuimin.group.logic.UserLogic;
import com.shuimin.group.mid.redis.RedisKey;
import com.shuimin.group.mid.redis.RedisService;
import com.shuimin.group.mid.redis.RedisUtil;
import com.shuimin.group.model.weixin.WeixinUser;
import com.shuimin.group.model.group.*;
import com.shuimin.group.service.GroupService;
import com.shuimin.group.service.WeixinUserService;
import pond.common.JSON;
import pond.common.S;
import pond.common.STRING;
import pond.common.f.Tuple;
import pond.db.Record;
import pond.web.Render;
import pond.web.Router;

import java.util.*;

public class GROUP extends Router {

    {
        /* 查询我可以参加的局 */
        /*
        gps_x:31.260797
        gps_y:120.754080
        distance:2000
        */
        get("/", (req, resp) -> {
            String userId = App.getUserId(req);
            Map<String,Object> params = new HashMap<>();
            if (STRING.notBlank(req.param("place_id")))
            {
                params.put("place_id", req.param("place_id"));
            }
            /* 传入你关注的局类型, 格式: ['1','2']*/
            String _group_type = req.param("group_type_id");
            if (STRING.notBlank(_group_type))
            {
                List<String> list = JSON.parseArray(_group_type);
                if (list!=null && list.size()>0)
                {
                    String[] group_type =list.toArray(new String[list.size()]);
                    params.put(GroupService.GROUP_QUERY_KEY_GROUP_TYPE, group_type);
                }
            }

            /* 传入你关注的局状态, 格式: ['create']*/
            String _group_status = req.param("group_status");
            if (STRING.notBlank(_group_status))
            {
                List<String> list = JSON.parseArray(_group_status);
                if (list!=null && list.size()>0)
                {
                    String[] group_status =list.toArray(new String[list.size()]);
                    params.put("group_status", group_status);
                }
            }

            String  gps_x  = req.param("gps_x");
            String  gps_y  = req.param("gps_y");
            String  distance = req.param("distance");
            if (STRING.notBlank(gps_x) && STRING.notBlank(gps_y) && STRING.notBlank(distance))
            {
                params.put(GroupService.GROUP_QUERY_KEY_GPS_DISTANSE, Tuple.t3(Double.valueOf(gps_x),Double.valueOf(gps_y),Double.valueOf(distance)));
            }

            S.echo("get all group params:"+ params);
            List<Map<String, Object>> ret = GroupService.allGroup(userId, params);
            if (params.containsKey(GroupService.GROUP_QUERY_KEY_GPS_DISTANSE))
            {
                Collections.sort(ret,  new Comparator<Map<String, Object>>() {
                    @Override
                    public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                        double a = (double)(o1.get("distance"));
                        double b = (double)(o2.get("distance"));
                        //升序
                        return a > b ? 1 : -1 ;
                    }
                });
            }
            resp.render(Render.page(ret, ret.size()));
        });

        /* 查询我加入的局 */
        get("/join", (req, resp) -> {
            String userId = App.getUserId(req);
            Map<String,Object> params = new HashMap<>();
            params.put(GroupService.GROUP_QUERY_KEY_ISJOIN,true);
            List<Map<String, Object>> ret = GroupService.allGroup(userId, params);
            resp.render(Render.page(ret, ret.size()));
        });

        /* 查询我创建的 */
        get("/found", (req, resp) -> {
            String userId = App.getUserId(req);
            Map<String,Object> params = new HashMap<>();
            params.put(GroupService.GROUP_QUERY_KEY_ISCREATOR,true);
            List<Map<String, Object>> ret = GroupService.allGroup(userId, params);
            resp.render(Render.page(ret, ret.size()));
        });

        get("/histroy", (req, resp) -> {
            String userId = App.getUserId(req);
        });

        get("/group_type", (req, resp) -> {
            resp.render(Render.json(GroupService.allGroupType()));
        });
        get("/group_type/:id", (req, resp) -> {
            String id = req.paramNonBlank("id", "id 不能为空");
            resp.render(Render.json(App.DB.get(t -> t.recordById(GroupType.class, id))));
        });

        /* 查询局信息 */
        get("/:id", (req, resp) -> {
            String id = req.paramNonBlank("id", "id 不能为空");
            String userId = App.getUserId(req);
            String groupKey = RedisService.getGroupKeyById(id);
            if (STRING.isBlank(groupKey))
            {
                resp.send(404, id+ " not found");
                return;
            }
            VGroup vGroup = new VGroup();
            vGroup.merge(RedisUtil.hscanObjectsFromKey(groupKey));
            //group_id:user_id:member
            List<String> memberKeyList = RedisUtil.keys(vGroup.id()+"*"+ RedisKey.MEMBER);
            List<Map<String, Object>> memberList = RedisUtil.hscanObjectFromKeys(memberKeyList);
            resp.render(Render.json( GroupService.transfer(userId,vGroup,memberList, new HashMap<>())));
        });

        /* 组个局 */
        post("/", (req, resp) -> {
            String userId = App.getUserId(req);
            Group group = (Group) Record.newEntity(Group.class).merge(req.toMap());
            group.setId(S.uuid.vid());
            group.set("user_id",userId);

            if (!UserLogic.isHasRight(UserRight.CREATE,userId))
            {
                resp.send(403, "you didn't have any times to create");
                return;
            }

            if (group.get("book_time") == null || "nan".equals(group.get("book_time").toString().toLowerCase()))
            {
                resp.send(400, "book_time is" + group.get("book_time"));
                return;
            }

            long book_time =  new Long(group.get("book_time"));
            if (    book_time <= (S.now() + Config.ms(Config.GROUP_CREATE_MAX_TIME))
                    && (book_time  >= (S.now() + Config.ms(Config.GROUP_CREATE_MIN_TIME))))
            {
                S.echo("new group "+ new Date(book_time).toString());
            }
            else {
                resp.send(400, "book_time ("+ new Date(book_time).toString()+") not permit, (set < 2 hours)" );
                return;
            }

            //时间不能等于"NaN"
            if (group.get("create_time") == null || "nan".equals(group.get("create_time").toString().toLowerCase()))
            {
                group.set("create_time", new Date().getTime());
            }

            if (group.get("group_status") == null)
            {
                group.set("group_status", GroupStatus.GROUP_STATUS_CREATE.val());
            }
            group.set("delay", "0");
            //todo 商店用户是1，普通为0
            group.set("create_type", "0");

            GroupMember groupMember = new GroupMember();
            groupMember.setId(S.uuid.vid());
            groupMember.set("group_id",group.id());
            groupMember.set("user_id", userId);
            groupMember.set("is_creator", "1");
            groupMember.set("op_status", String.valueOf(1));
            groupMember.set("op_time", String.valueOf(S.now()));
            App.DB.post(t -> {
                t.recordInsert(group);
                t.recordInsert(groupMember);
            });
            VGroup vGroup = App.DB.get(t -> t.recordById(VGroup.class, group.id()));
            WeixinUser weixinUser = App.DB.get(t -> t.recordById(WeixinUser.class, userId));
            VGroupMember vGroupMember = new VGroupMember();
            vGroupMember.merge(groupMember.toMap());
            vGroupMember.merge(weixinUser.toMap());
            Map<String,Map<String,String>> map = new HashMap<>();
            map.put(RedisService.getGroupKey(vGroup), vGroup.toJedisMap());
            map.put(RedisService.getMemberKey(group.id(), userId), RedisService.getMemberValue(vGroupMember));
            S.echo(map);
            if (!RedisUtil.hAdd(map))
            {
                resp.send(400, " add failed");
                return;
            }
            resp.status(201);
            resp.render(Render.json(group));
        });

        /* 参与 */
        post("/join/:id", (req, resp) -> {
            String groupId = req.param("id");
            String userId = App.getUserId(req);
            String key = RedisService.getGroupKeyById(groupId);

            if (!UserLogic.isHasRight(UserRight.JOIN,userId))
            {
                resp.send(403, "you didn't have any times to join");
                return;
            }
            if (STRING.isBlank(key))
            {
                resp.send(404,groupId + " not found");
                return;
            }
            List<String> memberKeyList = RedisUtil.keys(groupId+"*"+ RedisKey.MEMBER);
            List<Map<String, Object>> memberList = RedisUtil.hscanObjectFromKeys(memberKeyList);
            if (GroupService.isJoin(userId, memberList))
            {
                resp.send(400," had joined");
                return;
            }

            VGroup vGroup = new VGroup();
            vGroup.merge(RedisUtil.hscanObjectsFromKey(key));
            if (vGroup.get("max_num") == null)
            {
                resp.send(400, "max_num not fonud");
                return;
            }
            if (Integer.valueOf(vGroup.get("max_num").toString()).intValue() <= memberKeyList.size())
            {
                resp.send(403,"members is full");
                return;
            }
            WeixinUser weixinUser = WeixinUserService.getUserById(userId);
            VGroupMember vGroupMember = new VGroupMember();
            vGroupMember.setId(S.uuid.vid());
            vGroupMember.set("group_id",groupId);
            vGroupMember.set("user_id",userId);
            vGroupMember.set("is_creator","0");
            vGroupMember.set("op_status", "1");
            vGroupMember.set("op_time", String.valueOf(S.now()));
            vGroupMember.setUser(weixinUser);
            App.DB.post(t->{
                t.recordInsert(vGroupMember.groupMember());
            });

            Map<String,Map<String,String>> map = new HashMap<>();
            Map<String,String> newMember = RedisService.getMemberValue(vGroupMember);
            map.put(RedisService.getMemberKey(groupId, userId), newMember);
            S.echo(map);
            if (!RedisUtil.hAdd(map))
            {
                resp.send(400, "add failed");
                return;
            }
            memberList.add(RedisService.getMemberVal(vGroupMember));
            resp.status(201);
            resp.render(Render.json(GroupService.transfer(userId,vGroup,memberList, new HashMap<>())));
        });

        put("/delay/:id", (req,resp)->{
            String groupId = req.param("id");
            String userId = App.getUserId(req);
            String key = RedisService.getGroupKeyById(groupId);
            if (STRING.notBlank(key))
            {
                String delay = RedisUtil.hGetFieldVal(key, "delay");
                if ("0".equals(delay))
                {
                    RedisUtil.hSetFieldVal(key, "delay", String.valueOf(Config.GROUP_NOTIFY_DELAY_TIME));
                    resp.send(200,"ok");
                }
                else {
                    resp.send(400,"you had delay " + delay +" mins");
                }

            }
            else {
                resp.send(404,groupId + " not found");
                return;
            }
        });
        /* 离开 */
        del("/leave/:id", (req, resp) -> {
            String groupId = req.param("id");
            String userId = App.getUserId(req);
            String key = RedisService.getGroupKeyById(groupId);

            if (!UserLogic.isHasRight(UserRight.LEAVE,userId))
            {
                resp.send(403, "you didn't have any times to leave");
                return;
            }

            if (STRING.isBlank(key))
            {
                resp.send(404,groupId + " not found");
                return;
            }
            String memberKey = RedisService.getMemberKey(groupId,userId);
            if (!RedisUtil.exist(memberKey))
            {
                resp.send(400,"had not joined " + groupId);
                return;
            }

            Map<String, Object> vGroupMap = RedisUtil.hscanObjectsFromKey(key);
            if (userId.equals(vGroupMap.get("user_id")))
            {
                resp.send(403,"creator is forbidden to leave" );
                return;
            }

            VGroupMember vGroupMember = new VGroupMember();
            vGroupMember.setId(S.uuid.vid());
            vGroupMember.set("group_id",groupId);
            vGroupMember.set("user_id",userId);
            vGroupMember.set("is_creator","0");
            vGroupMember.set("op_status", String.valueOf(-1));
            vGroupMember.set("op_time", String.valueOf(S.now()));

            if(!RedisUtil.delKey(memberKey))
            {
                resp.send(404,"leave failed" );
                return;
            }
            App.DB.post(t->{
                t.recordInsert(vGroupMember.groupMember());
            });
            resp.status(201);
            VGroup vGroup = new VGroup();
            vGroup.merge(vGroupMap);
            List<String> memberKeyList = RedisUtil.keys(groupId+"*"+ RedisKey.MEMBER);
            List<Map<String, Object>> memberList = RedisUtil.hscanObjectFromKeys(memberKeyList);
            resp.render(Render.json(GroupService.transfer(userId,vGroup, memberList, new HashMap<>())));
        });

        /* 撤局 */
        del("/:id", (req, resp) -> {
            String groupId = req.param("id");
            String userId = App.getUserId(req);
            String key = RedisService.getGroupKeyById(groupId);

            if (!UserLogic.isHasRight(UserRight.CANCEL,userId))
            {
                resp.send(403, "you didn't have any times to cancel");
                return;
            }

            if (STRING.isBlank(key))
            {
                resp.send(404,groupId + " not found");
                return;
            }
            Map<String, Object> vGroupMap = RedisUtil.hscanObjectsFromKey(key);
            if (!userId.equals(vGroupMap.get("user_id")))
            {
                resp.send(403,"member is forbidden to cancel" );
                return;
            }
            //todo
            List<String> keyList = RedisService.getAllKeysAboutGroup(groupId,key);
            if (! RedisUtil.delKeys(keyList))
            {
                resp.send(400,"cancel failed" );
                return;
            }

            VGroup vGroup = new VGroup();
            vGroup.merge(vGroupMap);
            Group group = vGroup.group();
            group.set("group_status", GroupStatus.GROUP_STATUS_MANUAL_CANCEL.val());
            App.DB.post(t->{
                t.recordUpdate(group);
            });
            resp.send(200, "ok");
        });

        post("/group_type/", (req, resp) -> {
            String openId = req.paramNonBlank("id", "id 不能为空");
            GroupType groupType =  new GroupType();
            groupType.merge(req.toMap());
            groupType.setId(S.uuid.vid());
            App.DB.post(t -> {t.recordInsert(groupType); });
            resp.send(200);
        });
        del("/group_type/:id", (req, resp) -> {
            String id = req.paramNonBlank("id", "id 不能为空");
            App.DB.post(t -> {t.recordDelete(new GroupType().setId(id)); });
            resp.send(200);
        });
    }
}
